package com.zengdb.jdbc.util;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSourceFactory;


/*
 * 使用数据库连接池的jdbc工具类，负责获得数据库连接和释放连接资源
 */
public class DataSourceJdbcUtil {
	
	private static DataSource dataSource;
	private static ThreadLocal<Connection> threadConn = new ThreadLocal<>();
	
	static{
		try {
			InputStream in = DataSourceJdbcUtil.class.getClassLoader().getResourceAsStream("db.properties");
			Properties p = new Properties();
			p.load(in);
			in.close();
			dataSource = DruidDataSourceFactory.createDataSource(p);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	//工具类构造方法私有，禁止外部创建当前类的实例
	private DataSourceJdbcUtil(){}

	/**
	 * 获取数据库连接
	 *判断threadConn.get()是否为null，如果为null说明当前线程没有开启事务，那么从连接池中返回一个连接；
	 *如果不为null，说明已经开始了事务，那么直接返回threadConn.get()
	 * @return 返回数据库连接对象
	 * @throws SQLException
	 */
	public static Connection getConnection() throws SQLException{
		return threadConn.get() == null ? dataSource.getConnection() : threadConn.get();
	}
	
	/**
	 * 
	 *判断threadConn.get()是否为null，如果不为null，就抛出"事务已经开启"异常！
	 *如果null，那么从连接池中返回一个连接Connection对象，设置它为“手动提交”，把当前连接对象赋值给当前线程的变量。
	 * @throws SQLException
	 */
	public static void beginTranscation() throws SQLException {  
        Connection con = threadConn.get();  
        if(con != null) {  
            throw new SQLException("事务已经开启，在没有结束当前事务时，不能再开启事务！");  
        }  
        con = dataSource.getConnection();  
        con.setAutoCommit(false);  
        threadConn.set(con);  
    }  
      
	/**
	 * 
	 *判断threadConn.get()是否为null，如果为null，说明当前线程没有开启事务就提交事务，那么抛出异常；
	 *如果不为null，那么调用连接对象的commit()方法来提交事务；
	 *threadConn.remove()，这表示当前线程的事务已经结束！
	 * @throws SQLException
	 */
    public static void commitTransaction() throws SQLException {  
        Connection con = threadConn.get();  
        if(con == null) {  
            throw new SQLException("当前没有事务，所以不能提交事务！");  
        }  
        con.commit();  
        threadConn.remove(); 
    }  
      
    /**
	 * 
	 *判断threadConn.get()是否为null，如果为null，说明当前线程没有开启事务就回滚事务，那么抛出异常；
	 *如果不为null，那么调用连接对象的rollback()方法来回滚事务；
	 *threadConn.remove()，这表示当前线程的事务已经结束！
	 * @throws SQLException
	 */
    public static void rollbackTransaction() throws SQLException {  
        Connection con = threadConn.get();  
        if(con == null) {  
            throw new SQLException("当前没有事务，所以不能回滚事务！");  
        }  
        con.rollback();  
        threadConn.remove();  
    }  
	
	/**
	 *释放数据库连接资源 
	 * @param conn 数据库连接对象
	 * @param stat 执行数据库SQL语句的对象
	 * @param rs 执行SQL语名后退回的结果集对象
	 */
	public static void close(Connection conn,Statement stat,ResultSet rs) {
		try {
			if (rs != null) {
				rs.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (stat != null) {
					stat.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			} finally {
				try {
					if (conn != null) {
						conn.close();
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
}
